﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.IO;

namespace WebClass
{

    public class ImportTaskFromOutside
    {
        List<News> listNews;
        List<Exp> listExp;
        List<Experiments> listExperiments;
        int currentTaskID;
        ResearchDBDataContext researchDB;
        string errorMsg;
        public int LoadUsername(string usern)
        {
            int userID;
            var userResult = from user in researchDB.tb_users where user.name == usern select user;
            if (userResult.Count() != 0)
            {
                userID = userResult.First().ID;
            }
            else
            {
                userID = -1;
            }
            return userID;
        }
        public string Start(string taskName, string usernames, Stream streamXML)
        {
            errorMsg = "";
            ImportDataFromXML(streamXML);
            if (errorMsg != "")
            {
                return errorMsg;
            }
            string[] arrayUsername = usernames.Split(new char[1] {';'});
            List<int> listUserID;
            SaveTaskToDatabase(taskName, arrayUsername,out listUserID);
            AssignTask(listUserID);
            //trigger event to make ping bing start.
            CoverageOperation coverageOper = new CoverageOperation();
            coverageOper.TriggerEvent(currentTaskID);
            return errorMsg;
        }
        private void AssignTask(List<int> listUserID)
        {
            var experimentsResult = from e in researchDB.tb_experiments where e.taskID == currentTaskID 
                                    group e by e.newsID into g
                                    select g;
            int countUser = listUserID.Count;
            int count = 0;
            foreach (var e in experimentsResult)
            {
                if (count == countUser)
                {
                    count = 0;
                }
                foreach (var item in e)
                {
                    item.userID = listUserID.ElementAt(count);
                }
                ++count;
            }
            SubmitChanges();
        }

        private void SubmitChanges()
        {
            try
            {
                researchDB.SubmitChanges();
            }
            catch (Exception e)
            {
                errorMsg += e.Message + "<br/>";
            }
        }

        private bool ValidationXMLFile()
        {
            bool flag = true;
            foreach (Exp exp in listExp)
            {
                foreach (News news in listNews)
                {
                    int isExist = listExperiments.FindIndex(delegate(Experiments experiments)
                    {
                        if (experiments.ExpID == exp.ID && experiments.NewsID == news.ID)
                        {
                            return true;
                        }
                        return false;
                    });
                    if (isExist == -1)
                    {
                        flag = false;
                        errorMsg += "Experiment (ID:" + exp.ID + ") missing result for news (ID:" + news.ID + ") <br/>";
                    }
                }
            }
            return flag;
        }
        private void SaveTaskToDatabase(string taskName, string[] arrayUsername, out List<int> listUserID)
        {
            listUserID = new List<int>();

            if (!ValidationXMLFile())
            {
                return;
            }
            tb_task tb_t = new tb_task
            {
                name = taskName,
                createTime = System.DateTime.Now
            };
            researchDB.tb_tasks.InsertOnSubmit(tb_t);
            SubmitChanges();
            currentTaskID = tb_t.ID;
            
            foreach (News news in listNews)
            {
                var findNewsResult = from n in researchDB.tb_news where n.ID == news.ID select n;
                if (findNewsResult.Count() == 0)
                {
                    tb_new tb_n = new tb_new
                    {
                        ID = news.ID,
                        title = news.Title,
                        newsContent = news.Content,
                        market = news.Market
                    };

                    researchDB.tb_news.InsertOnSubmit(tb_n);
                }
                SubmitChanges();
            }

            foreach (Exp exp in listExp)
            {
                var findExpResult = from e in researchDB.tb_exps where e.ID.Equals(exp.ID) select e;
                if (findExpResult.Count() == 0)
                {
                    tb_exp tb_e = new tb_exp
                    {
                        ID = exp.ID.ToString(),
                        name = exp.Name
                    };
                    researchDB.tb_exps.InsertOnSubmit(tb_e);
                }
                SubmitChanges();
            }
            
            foreach (Experiments experiments in listExperiments)
            {
                tb_experiment tb_ex = new tb_experiment
                {
                    expID = experiments.ExpID.ToString(),
                    newsID = experiments.NewsID,
                    taskID = tb_t.ID,
                    isComplete = false
                };
                foreach (string s in experiments.Queries)
                {
                    tb_experimentsQuery tb_exQ = new tb_experimentsQuery
                    {
                        tb_experiment = tb_ex,
                        query = s,
                        rank = -1,
                        position = -2
                    };
                }
                researchDB.tb_experiments.InsertOnSubmit(tb_ex);
                SubmitChanges();
            }
            //save user info to database
            foreach (string username in arrayUsername)
            {
                //judge whether it has domain
                string strUsername = username;
                if (!strUsername.Contains("\\"))
                {
                    strUsername = "FAREAST\\" + username;
                }
                var findResult = from u in researchDB.tb_users where u.name == strUsername select u;
                if (findResult.Count() == 0)
                {
                    tb_user tb_u = new tb_user
                    {
                        name = strUsername
                    };
                    researchDB.tb_users.InsertOnSubmit(tb_u);
                    SubmitChanges();
                    listUserID.Add(tb_u.ID);
                }
                else
                {
                    foreach (var u in findResult)
                    {
                        listUserID.Add(u.ID);
                    }
                }
            }
        }

        public ImportTaskFromOutside()
        {
            listNews = new List<News>();
            listExp = new List<Exp>();
            listExperiments = new List<Experiments>();
            researchDB = new ResearchDBDataContext();
            currentTaskID = 0;
        }
        private void ImportDataFromXML(Stream streamXml)
        {
            XmlReader reader = XmlReader.Create(streamXml);
            reader.MoveToContent();
            // Parse the file and display each of the nodes.
             try
            {
                while (reader.Read())
                {
                    if (reader.NodeType == XmlNodeType.Element)
                    {
                        if (reader.Name == "NewsItem")
                        {
                            News news = new News();
                            reader.ReadToFollowing("ID");
                            news.ID = reader.ReadElementContentAsInt("ID", "");

                            reader.ReadToFollowing("Title");
                            news.Title = reader.ReadElementContentAsString("Title", "");

                            reader.ReadToFollowing("Content");
                            news.Content = reader.ReadElementContentAsString("Content", "");

                            reader.ReadToFollowing("Market");
                            news.Market = reader.ReadElementContentAsString("Market", "");
                            listNews.Add(news);
                        }
                        else if (reader.Name == "Experiment")
                        {
                            Exp exp = new Exp();

                            reader.ReadToFollowing("ID");
                            exp.ID = Guid.Parse(reader.ReadElementContentAsString("ID", ""));

                            reader.ReadToFollowing("Name");
                            exp.Name = reader.ReadElementContentAsString("Name", "");

                            listExp.Add(exp);
                        }
                        else if (reader.Name == "ExperimentResult")
                        {
                            Experiments experiments = new Experiments();

                            reader.ReadToFollowing("NewsID");
                            experiments.NewsID = reader.ReadElementContentAsInt("NewsID", "");

                            reader.ReadToFollowing("ExpID");
                            experiments.ExpID = Guid.Parse(reader.ReadElementContentAsString("ExpID", ""));

                            reader.ReadToFollowing("Queries");

                            if (reader.ReadToDescendant("Query"))
                            {
                                experiments.Queries.Add(reader.ReadElementContentAsString("Query", ""));
                                while (reader.ReadToNextSibling("Query"))
                                {
                                    experiments.Queries.Add(reader.ReadElementContentAsString("Query", ""));
                                }
                            }
                            listExperiments.Add(experiments);
                        }
                    }
                }

            }
            catch (XmlException x)
            {
                errorMsg += x.Message + "\n";
            }
        }
    }
}
